package github.fafaovo.common.item;

import github.fafaovo.common.Itemgroup.ExampleGroup;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import org.antlr.v4.runtime.misc.NotNull;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;

public class exampleitem extends Item {
    public exampleitem() {
        super(new Item.Properties().group(ExampleGroup.exampleGroup).maxStackSize(1));
    }


    //添加提示文本
    @Override
    @OnlyIn(Dist.CLIENT)
    public void addInformation(@Nonnull ItemStack stack, World world, @Nonnull List<ITextComponent> tooltip, @Nonnull ITooltipFlag flag)
    {

        stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(e ->
        {
            String msg = e.getEnergyStored() + " FE / " + e.getMaxEnergyStored() + " FE";
            tooltip.add(new StringTextComponent(msg));
        });
    }

    @Nullable
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) {
        return new ICapabilityProvider()
        {
            private final LazyOptional<IEnergyStorage> lazyOptional = LazyOptional.of(() -> new IEnergyStorage()
            {
                //canReceive 代表是否能输入能量，这里我们让它返回 true。
                //canExtract 代表是否能输出能量，这里我们也让它返回 true。
                //getMaxEnergyStored 代表内部能够存储的最大能量，这里我们设定在 48000。
                //getEnergyStored 代表内部存储的实际能量，这里我们通过物品的 NBT 读取能量。
                //extractEnergy 代表实施输出能量的行为，其中 simulate 参数代表是否为模拟行为。
                //receiveEnergy 代表实施输入能量的行为，其中 simulate 参数代表是否为模拟行为。
                //extractEnergy 和 receiveEnergy 各自均接收一个 int 作为参数，并生成 int 作为返回值。
                // 其中，作为参数传入的 int 代表期望输入输出的能量，而作为返回值的 int 代表实际输入输出的能量。这两个参数都非常重要，希望读者能够加以注意。
                @Override
                public int receiveEnergy(int maxReceive, boolean simulate)
                {
                    int energy = this.getEnergyStored();
                    int diff = Math.min(this.getMaxEnergyStored() - energy, maxReceive);
                    if (!simulate)
                    {
                        stack.getOrCreateTag().putInt("BatteryEnergy", energy + diff);
                    }
                    return diff;
                }

                @Override
                public int extractEnergy(int maxExtract, boolean simulate)
                {
                    int energy = this.getEnergyStored();
                    int diff = Math.min(energy, maxExtract);
                    if (!simulate)
                    {
                        stack.getOrCreateTag().putInt("BatteryEnergy", energy - diff);
                    }
                    return diff;
                }

                @Override
                public int getEnergyStored()
                {
                    if (stack.hasTag())
                    {
                        int energy = Objects.requireNonNull(stack.getTag()).getInt("BatteryEnergy");
                        return Math.max(0, Math.min(this.getMaxEnergyStored(), energy));
                    }
                    return 0;
                }

                @Override
                public int getMaxEnergyStored()
                {
                    return 192_000;
                }

                @Override
                public boolean canExtract()
                {
                    return true;
                }

                @Override
                public boolean canReceive()
                {
                    return true;
                }
            });;

            @Nonnull
            @Override
            public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side)
            {
                boolean isEnergy = Objects.equals(cap, CapabilityEnergy.ENERGY);
                return isEnergy ? this.lazyOptional.cast() : LazyOptional.empty();
            }
        };
    }


    @Override
    public @NotNull ActionResultType onItemUse(ItemUseContext context) {
        World world = context.getWorld();
        if (!world.isRemote)
        {
            TileEntity tileEntity = world.getTileEntity(context.getPos());
            if (tileEntity != null)
            {
                Direction side = context.getFace();
                tileEntity.getCapability(CapabilityEnergy.ENERGY, side).ifPresent(e ->
                {
                    this.transferEnergy(context, e);
                    this.notifyPlayer(context, e);
                });
            }
        }
        return ActionResultType.SUCCESS;
    }

    private void notifyPlayer(ItemUseContext context, IEnergyStorage e) {
        PlayerEntity player = context.getPlayer();
        if (player != null)
        {
            String msg = e.getEnergyStored() + " FE / " + e.getMaxEnergyStored() + " FE";
            player.sendMessage(new StringTextComponent(msg),player.getUniqueID());
        }
    }

    private void transferEnergy(@Nonnull ItemUseContext context, @Nonnull IEnergyStorage target)
    {
        context.getItem().getCapability(CapabilityEnergy.ENERGY).ifPresent(e ->
        {
            if(Screen.hasShiftDown()) //屏幕蹲下
            {
                if (target.canExtract()) //输出电
                {
                    int diff = e.getMaxEnergyStored() - e.getEnergyStored();
                    e.receiveEnergy(target.extractEnergy(diff, false), false);
                }
            }
            else
            {
                if (target.canReceive()) //输入电
                {
                    int diff = e.getEnergyStored();
                    e.extractEnergy(target.receiveEnergy(diff, false), false);
                }
            }



        });
    }
}
